<template>
  <div>
    <!-- Task Search Section -->
    <div class="card mb-5">
      <h2 class="text-2xl mb-5">🔍 查看现有任务</h2>

      <div class="mb-4">
        <label for="taskId" class="block mb-1.5 font-bold">任务ID:</label>
        <div class="relative w-full">
          <input
            type="text"
            id="taskId"
            class="input-field"
            v-model="taskId"
            placeholder="请输入或选择任务ID"
            autocomplete="off"
            @input="handleTaskIdInput"
            @focus="handleTaskIdFocus"
            @blur="handleTaskIdBlur"
            @keydown="handleTaskIdKeydown"
          />
          <div
            v-show="showTaskDropdown"
            class="absolute top-full left-0 right-0 bg-white border border-gray-300 border-t-0 rounded-b max-h-52 overflow-y-auto z-[1000]"
          >
            <div
              v-for="(task, index) in filteredTasks"
              :key="task.task_id"
              :class="['p-2.5 cursor-pointer border-b border-gray-200 hover:bg-gray-100', selectedOptionIndex === index ? 'bg-blue-600 text-white' : '']"
              @click="selectTask(task.task_id)"
            >
              <div>{{ task.task_id }}</div>
              <small :class="selectedOptionIndex === index ? 'text-white' : 'text-gray-600'">
                {{ task.status }} - {{ formatTimestamp(task.created_at) }}
              </small>
            </div>
          </div>
        </div>
      </div>

      <div class="mb-4">
        <label for="baseUrl" class="block mb-1.5 font-bold">S3基础URL (可选):</label>
        <input
          type="text"
          id="baseUrl"
          v-model="baseUrl"
          placeholder="默认使用API服务器配置"
          @change="saveConfiguration"
          class="input-field"
        />
      </div>

      <div class="mb-4">
        <label for="apiUrl" class="block mb-1.5 font-bold">API URL (可选):</label>
        <input
          type="text"
          id="apiUrl"
          v-model="apiUrl"
          placeholder="默认使用当前服务器配置"
          @change="saveConfiguration"
          class="input-field"
        />
      </div>

      <button @click="loadResults" class="btn-primary mr-2.5">🔍 查看结果</button>
      <button @click="clearResults" class="btn-primary bg-red-600 hover:bg-red-700">🗑️ 清空</button>
    </div>

    <!-- Loading -->
    <div v-show="isLoading" class="text-center py-5 text-gray-600">
      ⏳ 正在加载预测结果...
    </div>

    <!-- Error -->
    <div v-show="errorMessage" class="text-red-700 bg-red-100 border border-red-300 p-2.5 rounded mt-2.5">
      {{ errorMessage }}
    </div>

    <!-- Results -->
    <div v-show="showResults">
      <!-- Stats Section -->
      <StatsSection :stats="stats" />

      <!-- Quality Section -->
      <QualitySection v-show="showQualitySection" :quality="quality" />

      <!-- Images Section -->
      <div class="card mb-5">
        <h2 class="text-2xl mb-5">🖼️ 画框图预览</h2>
        <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-5 mt-5">
          <div
            v-for="(img, index) in images"
            :key="index"
            class="border border-gray-300 rounded-lg overflow-hidden bg-white"
          >
            <h3 class="bg-gray-100 m-0 p-2.5 border-b border-gray-300">{{ img.title }}</h3>
            <img
              :src="img.url"
              :alt="img.title"
              loading="lazy"
              class="w-full h-auto block min-h-[200px] cursor-pointer object-contain transition-transform hover:scale-105"
              @click="openModal(img.url, img.title)"
              @error="handleImageError($event, img)"
            />
            <div class="p-2.5 text-sm text-gray-600">
              {{ img.info }}<br />
              <small>文件: {{ img.filename }}</small><br />
              <small>路径: {{ img.path }}</small><br />
              <small class="text-gray-500">点击图片查看大图</small>
            </div>
          </div>
        </div>
      </div>

      <!-- Prediction Data -->
      <div class="card mb-5">
        <h2 class="text-2xl mb-5">📋 预测数据详情</h2>
        <div class="relative">
          <button
            :class="['absolute top-2.5 right-2.5 border-0 px-4 py-2 rounded cursor-pointer text-sm z-10 transition-colors', isCopied ? 'bg-purple-600 hover:bg-purple-700' : 'bg-green-600 hover:bg-green-700', 'text-white']"
            @click="copyJsonData"
            title="复制JSON数据"
          >
            {{ copyBtnText }}
          </button>
          <div class="bg-gray-100 border border-gray-300 rounded p-4 mt-4 whitespace-pre-wrap font-mono text-xs max-h-[300px] overflow-y-auto">
            {{ predictionDataText }}
          </div>
        </div>
      </div>
    </div>

    <!-- Image Modal -->
    <ImageModal
      v-if="showModal"
      :show="showModal"
      :imageUrl="currentImageUrl"
      :title="modalTitle"
      @close="closeModal"
    />
  </div>
</template>

<script>
import StatsSection from './StatsSection.vue'
import QualitySection from './QualitySection.vue'
import ImageModal from './ImageModal.vue'

export default {
  name: 'TaskView',
  components: {
    StatsSection,
    QualitySection,
    ImageModal
  },
  data() {
    return {
      taskId: '',
      baseUrl: 'http://k396a3ad.natappfree.cc',
      apiUrl: 'https://demo-1abed178a906e331.clonebot.work/detection-predict-api',
      taskHistory: [],
      showTaskDropdown: false,
      selectedOptionIndex: -1,
      isLoading: false,
      errorMessage: '',
      showResults: false,
      stats: {
        counts: [],
        totalTime: 'N/A',
        showTiming: false,
        basicTiming: [],
        modelTiming: [],
        pureInferenceTime: 0,
        showRayOverhead: false,
        rayOverhead: {},
        showFeatureDetails: false,
        featureDetails: []
      },
      showQualitySection: false,
      quality: {
        overallStatus: 'NG',
        isOverallOk: false,
        hasDetails: false,
        isExpanded: false,
        totalNgCount: 0,
        globalChecks: [],
        partChecks: []
      },
      images: [],
      predictionDataText: '',
      isCopied: false,
      copyBtnText: '📋 复制数据',
      showModal: false,
      currentImageUrl: '',
      modalTitle: '',
      currentTaskProcessingTime: null,
      currentTaskTimingDetails: null
    }
  },
  computed: {
    filteredTasks() {
      if (!this.taskId) return this.taskHistory.slice(0, 10)
      return this.taskHistory.filter(task => task.task_id.toLowerCase().includes(this.taskId.toLowerCase()))
    }
  },
  created() {
    this.restoreConfiguration()
    this.loadTaskHistory()
  },
  methods: {
    async loadTaskHistory() {
      try {
        const response = await fetch(`${this.apiUrl}/api/task_history?limit=50`)
        if (response.ok) {
          const data = await response.json()
          this.taskHistory = data.tasks || []
        }
      } catch (error) {
        console.error('加载任务历史失败:', error)
      }
    },
    handleTaskIdInput() {
      if (this.taskId.length >= 2 || this.taskId.length === 0) {
        this.showTaskDropdown = true
      } else {
        this.showTaskDropdown = false
      }
    },
    handleTaskIdFocus() {
      if (this.taskHistory.length > 0) {
        this.showTaskDropdown = true
      }
    },
    handleTaskIdBlur() {
      setTimeout(() => {
        this.showTaskDropdown = false
      }, 150)
    },
    handleTaskIdKeydown(event) {
      if (!this.showTaskDropdown) return
      switch (event.key) {
        case 'ArrowDown':
          event.preventDefault()
          this.selectedOptionIndex = Math.min(this.selectedOptionIndex + 1, this.filteredTasks.length - 1)
          break
        case 'ArrowUp':
          event.preventDefault()
          this.selectedOptionIndex = Math.max(this.selectedOptionIndex - 1, -1)
          break
        case 'Enter':
          if (this.selectedOptionIndex >= 0) {
            event.preventDefault()
            const task = this.filteredTasks[this.selectedOptionIndex]
            if (task) this.selectTask(task.task_id)
          } else {
            this.loadResults()
          }
          break
        case 'Escape':
          this.showTaskDropdown = false
          break
      }
    },
    selectTask(taskId) {
      this.taskId = taskId
      this.showTaskDropdown = false
    },
    loadTaskById(taskId) {
      this.taskId = taskId
      this.loadResults()
    },
    async loadResults() {
      if (!this.taskId.trim()) {
        this.errorMessage = '请输入任务ID'
        return
      }
      this.isLoading = true
      this.errorMessage = ''
      this.showResults = false
      try {
        const taskResult = await this.fetchTaskResult(this.taskId)
        if (taskResult && taskResult.result) {
          this.currentTaskProcessingTime = taskResult.processing_time
          this.currentTaskTimingDetails = taskResult.timing_details
          await this.displayResults(taskResult.result)
        } else if (taskResult && taskResult.status) {
          if (taskResult.status === 'pending') {
            this.errorMessage = '任务正在等待处理中,请稍后再试'
          } else if (taskResult.status === 'processing') {
            this.errorMessage = `任务正在处理中 (进度: ${taskResult.progress || 0}%),请稍后再试`
          } else if (taskResult.status === 'failed') {
            this.errorMessage = `任务处理失败: ${taskResult.error || '未知错误'}`
          } else {
            this.errorMessage = '任务结果尚未生成,请稍后再试'
          }
        } else {
          this.errorMessage = '无法获取任务信息,请检查任务ID是否正确'
        }
      } catch (error) {
        this.errorMessage = `加载结果失败: ${error.message}`
      } finally {
        this.isLoading = false
      }
    },
    async fetchTaskResult(taskId) {
      try {
        const response = await fetch(`${this.apiUrl}/api/get_result/${taskId}`)
        if (response.ok) {
          return await response.json()
        }
        return null
      } catch (error) {
        return null
      }
    },
    async displayResults(result) {
      if (result.summary) {
        let processingTime
        if (result.summary.processing_time) {
          processingTime = result.summary.processing_time.toString().includes('s')
            ? result.summary.processing_time
            : `${result.summary.processing_time}s`
        } else if (this.currentTaskProcessingTime) {
          processingTime = `${this.currentTaskProcessingTime.toFixed(2)}s`
        } else {
          processingTime = 'N/A'
        }
        const timing = result.summary.timing_details || this.currentTaskTimingDetails
        this.buildStatsData(result.summary, processingTime, timing)
        this.displayQualityResults(result.summary.quality_evaluation)
      }
      this.images = this.buildImagesArray(result)
      this.predictionDataText = JSON.stringify(result, null, 2)
      this.showResults = true
    },
    buildStatsData(summary, processingTime, timing) {
      this.stats.counts = [
        { label: '零件总数', value: summary.total_parts || 0 },
        { label: '钢印数量', value: summary.steel_stamp_count || 0 },
        { label: '镭雕数量', value: summary.laser_engraving_count || 0 },
        { label: 'R角数量', value: summary.r_corner_count || 0 },
        { label: '切割图片', value: summary.total_crops || 0 }
      ]
      this.stats.totalTime = processingTime
      if (timing) {
        this.buildTimingData(processingTime, timing)
      } else {
        this.stats.showTiming = false
        this.stats.showRayOverhead = false
        this.stats.showFeatureDetails = false
      }
    },
    buildTimingData(processingTime, timing) {
      this.stats.showTiming = true
      this.stats.basicTiming = [
        { label: '图像下载', value: `${(timing.download_time || 0).toFixed(3)}s` },
        { label: '图片切割', value: `${(timing.crop_time || 0).toFixed(3)}s` },
        { label: '画框图生成+上传', value: `${(timing.annotation_and_upload_time || timing.s3_upload_time || 0).toFixed(3)}s` },
        { label: '结果构建', value: `${(timing.result_build_time || 0).toFixed(3)}s` },
        { label: '结果序列化', value: `${(timing.serialization_time || 0).toFixed(3)}s` }
      ]
      this.stats.modelTiming = [
        { label: '🟢 零件检测', value: `${(timing.part_detection_time || 0).toFixed(3)}s` },
        { label: '🔵 钢印检测', value: `${(timing.steel_stamp_time || 0).toFixed(3)}s` },
        { label: '🔴 镭雕检测', value: `${(timing.laser_engraving_time || 0).toFixed(3)}s` },
        { label: '🟡 R角检测', value: `${(timing.r_corner_time || 0).toFixed(3)}s` }
      ]
      this.stats.pureInferenceTime =
        (timing.part_detection_time || 0) +
        (timing.steel_stamp_time || 0) +
        (timing.laser_engraving_time || 0) +
        (timing.r_corner_time || 0)
      const hasRayOverhead = timing.ray_call_overhead !== undefined && timing.ray_call_overhead > 0
      if (hasRayOverhead) {
        this.buildRayOverheadData(timing, this.stats.pureInferenceTime)
      } else {
        this.stats.showRayOverhead = false
      }
      const hasFeatureDetails = timing.feature_preprocessing_time !== undefined
      if (hasFeatureDetails) {
        this.stats.showFeatureDetails = true
        this.stats.featureDetails = [
          { label: '预处理时间', value: `${(timing.feature_preprocessing_time || 0).toFixed(3)}s` },
          { label: '后处理时间', value: `${(timing.feature_postprocessing_time || 0).toFixed(3)}s` }
        ]
      } else {
        this.stats.showFeatureDetails = false
      }
    },
    buildRayOverheadData(timing, pureInferenceTime) {
      this.stats.showRayOverhead = true
      this.stats.rayOverhead = {
        isHigh: timing.ray_call_overhead > 0.5,
        stats: [
          { label: '零件检测总时间', value: `${(timing.part_detection_total_time || 0).toFixed(3)}s` },
          { label: '零件检测开销', value: `${(timing.part_detection_overhead || 0).toFixed(3)}s` },
          { label: '特征检测总时间', value: `${(timing.feature_detection_total_time || 0).toFixed(3)}s` },
          { label: '特征检测开销', value: `${(timing.feature_detection_overhead || 0).toFixed(3)}s` },
          { label: 'Ray总开销', value: `${(timing.ray_call_overhead || 0).toFixed(3)}s` }
        ],
        pureInferenceTime: pureInferenceTime,
        totalRayOverhead: timing.ray_call_overhead || 0,
        totalAiTime: pureInferenceTime + (timing.ray_call_overhead || 0)
      }
    },
    buildImagesArray(result) {
      const images = []
      if (result.prediction_results && result.prediction_results.annotated_images) {
        const annotated = result.prediction_results.annotated_images
        if (annotated.complete) {
          images.push({
            title: '🎯 完整画框图 (所有检测类型)',
            url: this.replaceImageUrl(annotated.complete.url),
            info: `总检测数: ${annotated.complete.total_detections || 0}`,
            filename: annotated.complete.filename || '',
            path: annotated.complete.path || ''
          })
        }
        if (annotated.parts) {
          images.push({
            title: '🟢 零件检测',
            url: this.replaceImageUrl(annotated.parts.url),
            info: `检测数量: ${annotated.parts.count || 0}`,
            filename: annotated.parts.filename || '',
            path: annotated.parts.path || ''
          })
        }
        if (annotated.steel_stamp) {
          images.push({
            title: '🔵 钢印检测',
            url: this.replaceImageUrl(annotated.steel_stamp.url),
            info: `检测数量: ${annotated.steel_stamp.count || 0}`,
            filename: annotated.steel_stamp.filename || '',
            path: annotated.steel_stamp.path || ''
          })
        }
        if (annotated.laser_engraving) {
          images.push({
            title: '🔴 镭雕检测',
            url: this.replaceImageUrl(annotated.laser_engraving.url),
            info: `检测数量: ${annotated.laser_engraving.count || 0}`,
            filename: annotated.laser_engraving.filename || '',
            path: annotated.laser_engraving.path || ''
          })
        }
        if (annotated.r_corner) {
          images.push({
            title: '🟡 R角检测',
            url: this.replaceImageUrl(annotated.r_corner.url),
            info: `检测数量: ${annotated.r_corner.count || 0}`,
            filename: annotated.r_corner.filename || '',
            path: annotated.r_corner.path || ''
          })
        }
      }
      return images
    },
    displayQualityResults(qualityEvaluation) {
      if (!qualityEvaluation) {
        this.showQualitySection = false
        this.quality.hasDetails = false
        return
      }
      this.showQualitySection = true
      this.quality.overallStatus = qualityEvaluation.overall_status || 'NG'
      this.quality.isOverallOk = this.quality.overallStatus === 'OK'
      if (qualityEvaluation.checks) {
        this.quality.globalChecks = Object.entries(qualityEvaluation.checks).map(([checkName, checkResult]) => ({
          name: this.getCheckDisplayName(checkName),
          status: checkResult.status,
          message: checkResult.message
        }))
      } else {
        this.quality.globalChecks = []
      }
      if (qualityEvaluation.per_part_checks && qualityEvaluation.per_part_checks.length > 0) {
        this.quality.partChecks = qualityEvaluation.per_part_checks.map((partCheck, index) => {
          const checks = Object.entries(partCheck.checks || {}).map(([checkName, checkResult]) => ({
            name: this.getCheckDisplayName(checkName),
            status: checkResult.status,
            message: checkResult.message
          }))
          return {
            title: `零件 ${partCheck.part_id || index + 1}`,
            overallStatus: partCheck.overall_status || 'NG',
            checks: checks
          }
        })
      } else {
        this.quality.partChecks = []
      }
      let totalNgCount = 0
      totalNgCount += this.quality.globalChecks.filter(c => c.status === 'NG').length
      this.quality.partChecks.forEach(part => {
        totalNgCount += part.checks.filter(c => c.status === 'NG').length
      })
      this.quality.totalNgCount = totalNgCount
      this.quality.hasDetails = this.quality.globalChecks.length > 0 || this.quality.partChecks.length > 0
    },
    getCheckDisplayName(checkName) {
      const nameMap = {
        part_count: '零件数量',
        steel_stamp: '钢印检测',
        laser_engraving: '镭雕检测',
        r_corner: 'R角检测'
      }
      return nameMap[checkName] || checkName
    },
    clearResults() {
      this.taskId = ''
      this.showResults = false
      this.showQualitySection = false
      this.errorMessage = ''
      this.isLoading = false
    },
    handleImageError(event, img) {
      const target = event.target
      const errorDiv = document.createElement('div')
      errorDiv.className = 'bg-yellow-50 border border-yellow-200 p-2.5 text-center text-yellow-800 min-h-[100px] flex items-center justify-center flex-col'
      errorDiv.innerHTML = `
        <div>❌ 图片加载失败</div>
        <small>URL: ${img.url}</small>
        <small>路径: ${img.path}</small>
        <small>文件: ${img.filename}</small>
      `
      target.parentElement.replaceChild(errorDiv, target)
    },
    async copyJsonData() {
      if (!this.predictionDataText || this.predictionDataText.trim() === '') {
        alert('没有可复制的数据')
        return
      }
      try {
        if (navigator.clipboard && window.isSecureContext) {
          await navigator.clipboard.writeText(this.predictionDataText)
          this.showCopySuccess()
        } else {
          this.fallbackCopyTextToClipboard(this.predictionDataText)
        }
      } catch (err) {
        this.fallbackCopyTextToClipboard(this.predictionDataText)
      }
    },
    fallbackCopyTextToClipboard(text) {
      const textArea = document.createElement('textarea')
      textArea.value = text
      textArea.style.cssText = 'position:fixed;top:0;left:0;opacity:0'
      document.body.appendChild(textArea)
      textArea.focus()
      textArea.select()
      try {
        const successful = document.execCommand('copy')
        if (successful) {
          this.showCopySuccess()
        } else {
          alert('复制失败,请手动选择文本复制')
        }
      } catch (err) {
        alert('复制失败,请手动选择文本复制')
      }
      document.body.removeChild(textArea)
    },
    showCopySuccess() {
      this.isCopied = true
      this.copyBtnText = '✅ 已复制'
      setTimeout(() => {
        this.isCopied = false
        this.copyBtnText = '📋 复制数据'
      }, 2000)
    },
    openModal(imgSrc, title) {
      this.currentImageUrl = this.replaceImageUrl(imgSrc)
      this.modalTitle = title
      this.showModal = true
      document.body.style.overflow = 'hidden'
    },
    closeModal() {
      this.showModal = false
      document.body.style.overflow = 'auto'
    },
    formatTimestamp(timestamp) {
      return new Date(timestamp * 1000).toLocaleString()
    },
    replaceImageUrl(url) {
      if (!url || !this.baseUrl) return url
      return url.replace(/https?:\/\/([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+|minio:[0-9]+)/g, this.baseUrl)
    },
    saveConfiguration() {
      localStorage.setItem('s3BaseUrl', this.baseUrl)
      localStorage.setItem('apiUrl', this.apiUrl)
    },
    restoreConfiguration() {
      const savedBaseUrl = localStorage.getItem('s3BaseUrl')
      const savedApiUrl = localStorage.getItem('apiUrl')
      if (savedBaseUrl) this.baseUrl = savedBaseUrl
      if (savedApiUrl) this.apiUrl = savedApiUrl
    }
  }
}
</script>

